package com.pmstation.skin

import javax.imageio.ImageIO
import java.awt._
import datatransfer._
import event._
import image.{ColorModel, BufferedImage}
import java.io.File
import javax.swing.{JButton, JPanel, JFrame}

object Shaper{
  var currShaper:Shaper = _
  def main(args:Array[String]){
    val clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
    clipboard.addFlavorListener(new FlavorListener{
      def flavorsChanged(e: FlavorEvent) = {
        //println("clipboard flavorsChanged %s".format(e))
        if( clipboard.isDataFlavorAvailable(DataFlavor.imageFlavor) ){
          currShaper.nextImage()
        }
      }
    })

    new Shaper(new File("/tmp/nudes/4.jpg"))
  }
}

class Shaper(imgFile: File){
  Shaper.currShaper = this
  val scale=1
  val destDir = "/opt/project/scala-agent3/modules/skincolor/src/main/resources/skin"

//  val imgRes = this.getClass.getResource("/test2.jpg")
//  val img : BufferedImage = ImageIO.read(imgRes.openStream)

  val clipboard = Toolkit.getDefaultToolkit.getSystemClipboard
  val t = clipboard.getContents(null)

  var img = new BufferedImage(200,200, BufferedImage.TYPE_INT_RGB)
  img.getGraphics.drawString("no img in clipboard", 10, 10)
  if( imgFile!=null){
    img = ImageIO.read(imgFile)
  }else if( t!=null && t.isDataFlavorSupported(DataFlavor.imageFlavor) ){
    img = t.getTransferData(DataFlavor.imageFlavor).asInstanceOf[BufferedImage]
    clipboard.setContents(new StringSelection("image copied"), null)
  }

  var visited = Array.ofDim[Boolean](img.getWidth, img.getHeight)
  val imgCopy = new BufferedImage(img.getWidth, img.getHeight, BufferedImage.TYPE_INT_RGB)
  imgCopy.getGraphics.drawImage(img, 0,0, null)

  val f = new JFrame("Shaper")
  
  val c = new Canvas(){
    override def update(g: Graphics){
      paint(g)
    }
    override def paint(g: Graphics){
      g.drawImage(imgCopy, 0, 0, img.getWidth*scale, img.getHeight*scale, null)
    }

    override def getPreferredSize = new Dimension(img.getWidth*scale, img.getHeight*scale)
  }

  initFrame()

  var maxDiff=0
  var origColor=0

  var minselex, minseley, maxselex, maxseley = 0
  def visitFrom(pold:XY, delta:XY){
    val p = pold + delta
    if( p.x<0 || p.y<0 || p.x>=img.getWidth || p.y>=img.getHeight ){
      return
    }
    val color = img.getRGB(p.x, p.y)
    if( ColorDiff.diff(origColor, color) > 40 ){
      return
    }
    val colorOld = img.getRGB(pold.x, pold.y)
    //val colorDiff = ColorDiff.diff(color, colorOld)
    val colorDiff = diffAround(p, 2)

    if( !visited(p.x)(p.y) && colorDiff<=maxDiff ){

      minselex = minselex min p.x
      minseley = minseley min p.y
      maxselex = maxselex max p.x
      maxseley = maxseley max p.y

      visited(p.x)(p.y) = true
      imgCopy.setRGB(p.x, p.y, Color.BLUE.getRGB)
      c.invalidate()
      c.repaint()
      //println( colorDiff + " " + maxDiff + " " + new Color(color) )


      visitFrom(p,  XY(1,0))
      visitFrom(p,  XY(0,1))
      visitFrom(p,  XY(-1,0))
      visitFrom(p,  XY(0,-1))
    }

  }

  def save(){
    val inew = new BufferedImage(maxselex-minselex+1, maxseley-minseley+1, BufferedImage.TYPE_INT_RGB);
    for{
      i<-minselex to maxselex
      j<-minseley to maxseley
      x = i - minselex
      y = j - minseley
    }{
      if( visited(i)(j) ){
        inew.setRGB(x,y, img.getRGB(i,j))
      }else{
        inew.setRGB(x,y, Color.WHITE.getRGB)
      }
    }
    var idx=1
    def file = new File(destDir,"shaper"+idx+".png")
    while(file.exists){
      idx += 1
    }
    val outFile = file
    ImageIO.write(inew, "png", outFile)
    println("%s ready".format(outFile))
  }

  def diffAround(p:XY, radius:Int) = {
    val d = new ColorDiff
    for( i<- -radius to radius; j <- -radius to radius ){
      val xi = p.x + i
      val yi = p.y + i
      if( i*i+j*j <= radius*radius ){
        if( xi>=0 && yi>=0 && xi<img.getWidth && yi<img.getHeight ){
          d.update( img.getRGB(xi, yi) )
        }else{
          d.update( 0 )
        }
      }
    }
    d.maxDiff
  }

  def nextImage(){
    f.dispose()
    concurrent.ops.spawn(new Shaper(null))
  }

  def initFrame(){
    var start : XY = null



    c.addMouseListener(new MouseAdapter(){
      override def mouseReleased(e: MouseEvent) = {
        if( e.isControlDown ){
          save()
//        } else if( e.isShiftDown ){
//          imgCopy.getGraphics.drawImage(img, 0,0, null)
//          visited = Array.ofDim[Boolean](img.getWidth, img.getHeight)
//          c.invalidate()
//          c.repaint()
        }else{
          start = XY( e.getX/scale, e.getY/scale )

          println("clicked point %s".format(start))
//          start = XY(58,36)
//          println("clicked point replaced with %s".format(start))

          origColor = img.getRGB(start.x, start.y)
          maxDiff = 60 //diffAround(start, 5)
          visitFrom(start, XY(0,0))
        }
      }
    });

    f.addWindowListener(new WindowAdapter{
      override def windowClosing(e: WindowEvent) = {
        nextImage()
      }
    })

    val panel = new JPanel
    panel.setLayout(new GridLayout(1,0))
    panel.add(button("Save", () => save()))
    panel.add(button("Next image", () => nextImage()))

    c.setBackground(Color.WHITE)
    f.add(c)
    f.add(panel, BorderLayout.SOUTH)
    f.pack()
    f.setVisible(true)
  }

  def button(txt: String, action: ()=>Unit)={
    val b = new JButton(txt)
    b.addActionListener(new ActionListener{
      def actionPerformed(e: ActionEvent) = action()
    })
    b
  }

}